#define IER_ELSI 0x04 /* rx line status */
#define IER_EMSI 0x08 /* MODEM status */
-/* FIFO control register */
+/* Interrupt Identification Register */
+#define IIR_NOINT 0x01 /* no interrupt pending */
+#define IIR_IMASK 0x06 /* interrupt identity: */
+#define IIR_LSI 0x06 /* - rx line status */
+#define IIR_RDAI 0x04 /* - rx data recv'd */
+#define IIR_THREI 0x02 /* - tx reg. empty */
+#define IIR_MSI 0x00 /* - MODEM status */
+
+/* FIFO Control Register */
#define FCR_ENABLE 0x01 /* enable FIFO */
#define FCR_CLRX 0x02 /* clear Rx FIFO */
#define FCR_CLTX 0x04 /* clear Tx FIFO */
#define FCR_TRG8 0x80 /* Rx FIFO trig lev 8 */
#define FCR_TRG14 0xc0 /* Rx FIFO trig lev 14 */
-/* Line control register */
+/* Line Control Register */
#define LCR_DLAB 0x80 /* Divisor Latch Access */
/* Modem Control Register */
struct serial_port *port = dev_id;
struct ns16550 *uart = port->uart;
- if ( (ns_read_reg(uart, IIR) & 7) == 2 )
+ while ( !(ns_read_reg(uart, IIR) & IIR_NOINT) )
+ {
serial_tx_interrupt(port, regs);
- else
serial_rx_interrupt(port, regs);
+ }
}
static int ns16550_tx_empty(struct serial_port *port)
void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
{
char c;
- serial_rx_fn fn;
+ serial_rx_fn fn = NULL;
unsigned long flags;
- BUG_ON(!port->driver);
- BUG_ON(!port->driver->getc);
+ spin_lock_irqsave(&port->lock, flags);
- for ( ; ; )
+ if ( port->driver->getc(port, &c) )
{
- spin_lock_irqsave(&port->lock, flags);
-
- if ( !port->driver->getc(port, &c) )
- break;
-
- fn = NULL;
if ( port->rx != NULL )
fn = port->rx;
else if ( (c & 0x80) && (port->rx_hi != NULL) )
fn = port->rx_lo;
else if ( (port->rxbufp - port->rxbufc) != SERIAL_RXBUFSZ )
port->rxbuf[MASK_SERIAL_RXBUF_IDX(port->rxbufp++)] = c;
-
- spin_unlock_irqrestore(&port->lock, flags);
-
- if ( fn != NULL )
- (*fn)(c & 0x7f, regs);
-
- cpu_relax();
}
spin_unlock_irqrestore(&port->lock, flags);
+
+ if ( fn != NULL )
+ (*fn)(c & 0x7f, regs);
}
void serial_tx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
int i;
unsigned long flags;
- BUG_ON(!port->driver);
- BUG_ON(!port->driver->tx_empty);
- BUG_ON(!port->driver->putc);
-
spin_lock_irqsave(&port->lock, flags);
- for ( i = 0; i < port->tx_fifo_size; i++ )
+ if ( port->driver->tx_empty(port) )
{
- if ( port->txbufc == port->txbufp )
- break;
- port->driver->putc(
- port, port->txbuf[MASK_SERIAL_TXBUF_IDX(port->txbufc++)]);
+ for ( i = 0; i < port->tx_fifo_size; i++ )
+ {
+ if ( port->txbufc == port->txbufp )
+ break;
+ port->driver->putc(
+ port, port->txbuf[MASK_SERIAL_TXBUF_IDX(port->txbufc++)]);
+ }
}
spin_unlock_irqrestore(&port->lock, flags);
void serial_puts(int handle, const char *s)
{
- while ( *s != '\0' )
- serial_putc(handle, *s++);
+ struct serial_port *port = &com[handle & SERHND_IDX];
+ unsigned long flags;
+ char c;
+
+ if ( (handle == -1) || !port->driver || !port->driver->putc )
+ return;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ while ( (c = *s++) != '\0' )
+ {
+ if ( (c == '\n') && (handle & SERHND_COOKED) )
+ __serial_putc(port, '\r');
+
+ if ( handle & SERHND_HI )
+ c |= 0x80;
+ else if ( handle & SERHND_LO )
+ c &= 0x7f;
+
+ __serial_putc(port, c);
+ }
+
+ spin_unlock_irqrestore(&port->lock, flags);
}
char serial_getc(int handle)